home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_498 / zoomdaemon / source / zoom-main.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  381 lines

  1. /*
  2.  *  ZOOM-DAEMON   A program that implements Zoom gadgets for all Intuition
  3.  *                windows that are opened while it is running.
  4.  *
  5.  *              Copyright 1989 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  */
  8.  
  9. #include "Zoom-Main.h"
  10. #include "Zoom-Daemon.h"
  11.  
  12. struct IntuitionBase *IntuitionBase = NULL;
  13. extern struct SysBase *SysBase;
  14.  
  15. static char *program   = PROGRAM;
  16. static char *copyright = COPYRIGHT;
  17.  
  18. static char *handler   = HANDLERCODE;       /* The name of the handler file */
  19. #define HANDLER          &(handler[2])      /* Handler without the L: */
  20.  
  21. static struct Zoom_HandlerInfo *Zoom_HandlerData; /* data shared with handler */
  22. static long Segment;                        /* The loaded handler segment */
  23.  
  24. static struct ExtGadget *FirstZoom;         /* The list of zoom gadgets */
  25.  
  26. static struct MsgPort *InputPort;           /* To talk to Input.Device */
  27. static struct IOStdReq *InputBlock;         /* IO block for Input.Device */
  28. static int    InputDevice;                  /* Is Input.Device open? */
  29. static int    VectorsSet;                   /* TRUE after SetFunction */
  30.  
  31.  
  32. /*
  33.  *  DoExit()
  34.  *
  35.  *  General purpose error-exit routine.  Print an error message if one was
  36.  *  supplied (it can have up to three parameters), and then clean up any
  37.  *  memory, libraries, etc. that need to be handled before exiting.
  38.  */
  39.  
  40. static void DoExit(s,x1,x2,x3)
  41. char *s, *x1, *x2, *x3;
  42. {
  43.    long status = EXIT_OK;
  44.    
  45.    if (s != NULL)
  46.    {
  47.       printf(s,x1,x2,x3);
  48.       printf("\n");
  49.       status = EXIT_ERROR;
  50.    }
  51.    if (VectorsSet)      UnSetVectors();
  52.    if (InputDevice)     CloseDevice(InputBlock);
  53.    if (InputBlock)      DeleteStdIO(InputBlock);
  54.    if (InputPort)       DeletePort(InputPort);
  55.    if (Segment)         UnLoadSeg(Segment);
  56.    if (IntuitionBase)   CloseLibrary(IntuitionBase);
  57.    exit(status);
  58. }
  59.  
  60.  
  61. /*
  62.  *  CheckLibOpen()
  63.  *
  64.  *  Call OpenLibrary() for the specified library, and check that the 
  65.  *  open succeeded.
  66.  */
  67.  
  68. static void CheckLibOpen(lib,name,rev)
  69. APTR *lib;
  70. char *name;
  71. int rev;
  72. {
  73.    extern APTR OpenLibrary();
  74.  
  75.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  76.       DoExit("Can't open %s",name);
  77. }
  78.  
  79.  
  80. /*
  81.  *  LoadHandler()
  82.  *
  83.  *  Try to LoadSeg the handler from the current directory, and if it is not
  84.  *  found, try the L: directory.  If neither can be loaded, exit with an
  85.  *  error message.  Once the handler is loaded, call the Setup routine
  86.  *  in the handler code and pass the loader version number.  The handler will
  87.  *  check the version for compatibility and returns NULL if there is a
  88.  *  mismatch, or a pointer to the shared data if everything is OK.
  89.  *  Check the handler version number, and then store the loader version
  90.  *  and the segment list pointer for use in unloading the handler later.
  91.  *  The MsgPort is the first item in the Zoom_Handler structure.  It is used
  92.  *  to link the information into the system port list, where we can find it
  93.  *  later.
  94.  */
  95.  
  96. void LoadHandler(thePort)
  97. struct MsgPort **thePort;
  98. {
  99.    struct Zoom_HandlerInfo *(*Setup)();
  100.    
  101.    if ((Segment = LoadSeg(HANDLER)) == NULL)
  102.       if ((Segment = LoadSeg(handler)) == NULL)
  103.         DoExit("Can't load %s",handler);
  104.    Setup = (struct Zoom_HandlerInfo *(*)()) ((Segment << 2) + 4);
  105.    
  106.    Zoom_HandlerData = (*Setup)(LOADVERS);
  107.    if (Zoom_HandlerData)
  108.    {
  109.       if (var(MajVers) < MINHMAJVERS ||
  110.          (var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
  111.              DoExit("Version mismatch with %s",HANDLER);
  112.       *thePort = &(Zoom_HandlerData->Zoom_Port);
  113.    } else {
  114.       DoExit("%s reports a version mismatch",HANDLER);
  115.    }
  116.    
  117.    var(Segment)  = Segment;
  118. }
  119.  
  120.  
  121. /*
  122.  *  TellInputDevice()
  123.  *
  124.  *  Create a port and I/O block, then open the input device.  Set up the
  125.  *  I/O block to add or remove the input handler, and send the request
  126.  *  to the input device.  Finally, close the device and delete the
  127.  *  I/O block and port.
  128.  */
  129.  
  130. void TellInputDevice(function)
  131. int function;
  132. {
  133.    long status;
  134.    extern struct MsgPort *CreatePort();
  135.    extern struct IOStdReq *CreateStdIO();
  136.  
  137.    if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
  138.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  139.       DoExit("Can't Create Standard IO Block");
  140.    InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
  141.    if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
  142.    
  143.    InputBlock->io_Command = (long) function;
  144.    InputBlock->io_Data    = (APTR) var(Zoom_Interrupt);
  145.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  146.  
  147.    CloseDevice(InputBlock); InputDevice = FALSE;
  148.    DeleteStdIO(InputBlock); InputBlock = NULL;
  149.    DeletePort(InputPort);   InputPort = NULL;
  150. }
  151.  
  152.  
  153. /*
  154.  *  SetVectors()
  155.  *
  156.  *  Set the Intuition library vectors for the routines specified by the
  157.  *   handler.  Save the old routine pointers for later replacement.
  158.  */
  159.  
  160. void SetVectors()
  161. {
  162.    VAR(OldOpenWindow)  =
  163.       SetFunction(IntuitionBase,&LVOOpenWindow,var(aOpenWindow));
  164.    VAR(OldCloseWindow) =
  165.       SetFunction(IntuitionBase,&LVOCloseWindow,var(aCloseWindow));
  166.    VAR(OldAddGadget) =
  167.       SetFunction(IntuitionBase,&LVOAddGadget,var(aAddGadget));
  168.    VAR(OldAddGList) =
  169.       SetFunction(IntuitionBase,&LVOAddGList,var(aAddGList));
  170.    VectorsSet = TRUE;
  171. }
  172.  
  173.  
  174. /*
  175.  *  UnSetVectors()
  176.  *
  177.  *  Replace the old Intuition library vectors, but make sure that no one
  178.  *  else has changed them behind our back.  If they are not the same as
  179.  *  what we set them to originally, then put back the ones that we found,
  180.  *  and return an error status.
  181.  */
  182.  
  183. int UnSetVectors()
  184. {
  185.    long NewOpenWindow;
  186.    long NewCloseWindow;
  187.    long NewAddGadget;
  188.    long NewAddGList;
  189.    int status = TRUE;
  190.  
  191.    Forbid();
  192.    NewOpenWindow  =
  193.       SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow));
  194.    NewCloseWindow =
  195.       SetFunction(IntuitionBase,&LVOCloseWindow,VAR(OldCloseWindow));
  196.    NewAddGadget =
  197.       SetFunction(IntuitionBase,&LVOAddGadget,VAR(OldAddGadget));
  198.    NewAddGList =
  199.       SetFunction(IntuitionBase,&LVOAddGList,VAR(OldAddGList));
  200.    if (NewOpenWindow  != (long) var(aOpenWindow)  ||
  201.        NewCloseWindow != (long) var(aCloseWindow) ||
  202.        NewAddGadget   != (long) var(aAddGadget)   ||
  203.        NewAddGList    != (long) var(aAddGList))
  204.    {
  205.       SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow);
  206.       SetFunction(IntuitionBase,&LVOCloseWindow,NewCloseWindow);
  207.       SetFunction(IntuitionBase,&LVOAddGadget,NewAddGadget);
  208.       SetFunction(IntuitionBase,&LVOAddGList,NewAddGList);
  209.       status = FALSE;
  210.    }
  211.    Permit();
  212.    return(status);
  213. }
  214.  
  215.  
  216. /*
  217.  *  SetVariables()
  218.  *
  219.  *  The Zoom_HandlerData structure is used to allow the loading program to
  220.  *  set up variables needed by the handler (like Intuitionbase, etc.).  This
  221.  *  keeps the handler code to a minimum.  The loader retains pointers to the
  222.  *  linked lists, in case it needs to free memory on behalf of the handler.
  223.  */
  224.  
  225. void SetVariables(thePort)
  226. struct MsgPort *thePort;
  227. {
  228.    VAR(IntuitionBase) = IntuitionBase;
  229.    VAR(SysBase) = SysBase;
  230.    VAR(FirstZoom) = NULL;
  231. }
  232.  
  233.  
  234. /*
  235.  *  GetVariables()
  236.  *
  237.  *  Look up the values stored in the Zoom_HandlerData structure.  The 
  238.  *  Intuition library already was opened, and we will need to close it.
  239.  *  The data in the linked lists may need to be freed.
  240.  */
  241.  
  242. void GetVariables(thePort)
  243. struct MsgPort *thePort;
  244. {
  245.    Zoom_HandlerData = (struct Zoom_HandlerInfo *)thePort;
  246.    IntuitionBase = VAR(IntuitionBase);
  247.    FirstZoom = VAR(FirstZoom);
  248. }
  249.  
  250.  
  251. /*
  252.  *  SetupWindows()
  253.  *
  254.  *  Looks through the Intuition screen and windows lists and
  255.  *  calls the Handler's SetupWindow routine to add the imagery to
  256.  *  each pre-existing window.
  257.  *
  258.  *  All of this is done in Forbid() mode so that the list won't change 
  259.  *  while we're looking.
  260.  */
  261.  
  262. static void SetupWindows()
  263. {
  264.    struct Screen *theScreen;
  265.    struct Window *theWindow;
  266.    
  267.    if (var(SetupWindow))
  268.    {
  269.       Forbid();
  270.       theScreen = IntuitionBase->FirstScreen;
  271.       while (theScreen)
  272.       {
  273.          theWindow = theScreen->FirstWindow;
  274.          while (theWindow)
  275.          {
  276.             VAR(SetupWindow)(theWindow);
  277.             theWindow = theWindow->NextWindow;
  278.          }
  279.          theScreen = theScreen->NextScreen;
  280.       }
  281.       Permit();
  282.    }
  283. }
  284.  
  285.  
  286. /*
  287.  *  FreeAllZoomGadgets();
  288.  *
  289.  *  Goes through the linked list of zoom gadgets and removes each
  290.  *  from its associated window, refreshes the window, and frees
  291.  *  the memory associated with the zoom gadget.
  292.  */
  293.  
  294. void FreeAllZoomGadgets()
  295. {
  296.    struct ExtGadget *theGadget;
  297.  
  298.    while (FirstZoom)
  299.    {
  300.       theGadget = FirstZoom;
  301.       FirstZoom = theGadget->Next;
  302.       RemoveGadget(theGadget->Window,&(theGadget->Gadget));
  303.       RefreshWindowFrame(theGadget->Window);
  304.       FreeMem(theGadget,EXTGADGETSIZE);
  305.    }
  306.    FirstZoom = NULL;
  307. }
  308.  
  309.  
  310. /*
  311.  *  Main()
  312.  *
  313.  *  Look for the Zoom-Daemon port.
  314.  *  If the port does not exist, then Zoom-Daemon is not active, so:
  315.  *    Open Intuition.
  316.  *    Load the handler code and check its version.
  317.  *    Add the port (supplied by the handler) into the system list so we
  318.  *      can find it later.
  319.  *    Set the variables needed by the handler.
  320.  *    Set the Intuition Library vectors for the handler routines
  321.  *    Add the input handler into the Input Device chain
  322.  *    Retro-fit existing windows to include the Zoom Gadgets
  323.  *    Notify the user that all is ready.
  324.  *  else (the port already exists, so Zoom-Daemon alreay is active)
  325.  *    Get the pointer to the Zoom_HandlerData structure from the port,
  326.  *      and get any variables we need from the structure.
  327.  *    Check that the loader versions are compatible.
  328.  *    Remove the input handler from the Input Device chain
  329.  *    Try to remove the SetFunction calls.
  330.  *    If successfull, then
  331.  *      Remove the port from the system list.
  332.  *      Cleanup and windows that are still using the Zoom Gadgets
  333.  *      Unload the handler segment list.
  334.  *      Notify the user that Zoom-Daemon is deactivated.
  335.  *      Close Intuition.
  336.  *    else (we could not replace the functions)
  337.  *      Put back the input handler
  338.  *      Inform the user that Zoom-Daemon can not be removed
  339.  */
  340.  
  341. void main()
  342. {
  343.    struct MsgPort *NamedPort;
  344.  
  345.    NamedPort = FindPort(PORTNAME);
  346.    if (NamedPort == NULL)
  347.    {
  348.       CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  349.       LoadHandler(&NamedPort);
  350.       AddPort(NamedPort);
  351.       SetVariables(NamedPort);
  352.       SetVectors(NamedPort);
  353.       TellInputDevice(IND_ADDHANDLER);
  354.       SetupWindows();
  355.       printf("%s v%d.%d.%d Installed\n",program,
  356.          var(MajVers),var(MinVers),LOADVERS);
  357.    } else {
  358.       GetVariables(NamedPort);
  359.       if (var(MinLoadVers) > LOADVERS || var(MajVers) < MINHMAJVERS ||
  360.          (var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
  361.       {
  362.          printf("Loader version mismatch\n");
  363.          printf("%s not removed\n",program);
  364.       } else {
  365.          TellInputDevice(IND_REMHANDLER);
  366.          if (UnSetVectors(NamedPort))
  367.          {
  368.             RemPort(NamedPort);
  369.             FreeAllZoomGadgets();
  370.             UnLoadSeg(var(Segment));
  371.             printf("%s removed\n",program);
  372.             CloseLibrary(IntuitionBase);
  373.          } else {
  374.             TellInputDevice(IND_ADDHANDLER);
  375.             printf("SetFunction vectors have been changed!\n");
  376.             printf("Cannot remove %s\n",program);
  377.          }
  378.       }
  379.    }
  380. }
  381.